package org.nvframe.component.physics.motion;

import org.newdawn.slick.geom.Vector2f;
import org.nvframe.component.AbstractComponent;
import org.nvframe.component.physics.state.PhysicsPosition;
import org.nvframe.component.state.Position;
import org.nvframe.entity.Entity;
import org.nvframe.event.EventService;
import org.nvframe.event.eventtype.MotionEvent;
import org.nvframe.event.eventtype.UpdateEvent;
import org.nvframe.event.eventtype.UpdateListener;
import org.nvframe.util.Settings;

/**
 * 
 * @author Nik Van Looy
 */
public class ToDirectionMotion extends AbstractComponent implements UpdateListener {

	private float moveSpeed;
	private float velX;
	private float velY;
	private float offset;
	
	private boolean init;

	public ToDirectionMotion(String id, Entity owner, Settings settings) {
		super(id, owner);
		
		moveSpeed = settings.getFloat("velocity");	
		offset = settings.getFloat("offset", 0);	
		
		init = false;
		
		EventService.getInstance().addEventListener(this);
	}
	
	/**
	 * 
	 * @param startCoords
	 * @param targetCoords
	 * @param offset
	 */
	public void startMotion(Vector2f startCoords, Vector2f targetCoords, float offset) {
		this.offset = offset;
		startMotion(startCoords.copy(), targetCoords.copy());
	}

	/**
	 * 
	 * @param startCoords
	 * @param targetCoords
	 */
	public void startMotion(Vector2f startCoords, Vector2f targetCoords) {

		Position position = (Position) owner.getComponent(Position.class);
		float radDirection = (float) Math.atan2(targetCoords.getY() - startCoords.getY(), 
				targetCoords.getX() - startCoords.getX());

		if(position == null)
			return;

		position.setDirection((float) Math.toDegrees(radDirection));
		
		position.setXY(startCoords.getX() + (float) Math.cos(radDirection) * offset, 
				startCoords.getY() + (float) Math.sin(radDirection) * offset);
		
		velX = (float) Math.cos(radDirection) * moveSpeed;
		velY = (float) Math.sin(radDirection) * moveSpeed;
		
		init = true;
	}

	@Override
	public void onUpdate(UpdateEvent event) {
		int delta = event.getDelta();
		
		if(!init)
			return;
		
		PhysicsPosition position = (PhysicsPosition) owner.getComponent(PhysicsPosition.class);
		
		position.adjustVelocity(velX * delta, velY * delta);
		
		boolean motion = true;
		
		// fire motion event when object is moving
		// TODO expand functionality of this class
		if(motion)
			EventService.getInstance().fireEvent(new MotionEvent(getOwner()), getOwner());
	}
	
	@Override
	public void removed(Entity entity) {
		EventService.getInstance().removeEventListener(this);
	}
}
